package com.ruoyi.app.controller.member.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.app.controller.member.entity.BO.AppletAuthBO;
import com.ruoyi.app.controller.member.entity.BO.AppletUserBO;
import com.ruoyi.app.controller.member.mapper.IMemberMapper;
import com.ruoyi.app.controller.member.service.IAppletService;
import com.ruoyi.app.controller.shop.service.IShopAppletService;
import com.ruoyi.app.framework.manager.AsyncManager;
import com.ruoyi.app.framework.manager.factory.ApiAsyncFactory;
import com.ruoyi.common.entity.DO.member.MemberDO;
import com.ruoyi.common.entity.DO.shop.ShopAppletDO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class AppletServiceImpl implements IAppletService {

    private RestTemplate restTemplate = new RestTemplate();

    @Value("${api.host}")
    private String host;

    @Value("${applet.authUrl}")
    private String authUrl;

    @Value("${applet.accessTokenUrl}")
    private String accessTokenUrl;

    @Value("${applet.phoneAuthUrl}")
    private String phoneAuthUrl;

    @Autowired
    private IMemberMapper memberMapper;

    @Autowired
    private IShopAppletService shopAppletService;

    @Override
    @Synchronized
    public MemberDO auth(AppletAuthBO appletAuthBO) throws BusinessException {
        //TODO：查询店铺的appId和secret
        ShopAppletDO shopApplet = shopAppletService.getDetailByShopId(appletAuthBO.getShopId());
        if (shopApplet == null || shopApplet.getIsEnable() == null || shopApplet.getIsDelete() == 1) {
            throw new BusinessException("请联系运营平台重新开通小程序！");
        }
        if (shopApplet.getIsEnable() == 0) {
            throw new BusinessException("请联系运营平台重新上架小程序！");
        }
        String resultStr = restTemplate.getForObject(
                authUrl, String.class,
                shopApplet.getAppletAppId(),
                shopApplet.getAppletSecret(),
                appletAuthBO.getCode(),
                "authorization_code");
        if (StringUtils.isEmpty(resultStr)) {
            throw new BusinessException("网络异常");
        }
        AppletUserBO appletUserBO = new AppletUserBO();
        try {
            JSONObject resultObj = JSONObject.parseObject(resultStr);
            if (resultObj.containsKey("errcode") && resultObj.getIntValue("errcode") != 0) {
                System.out.println(resultObj);
                throw new BusinessException("授权信息错误");
            } else {
                appletUserBO.setOpenid(resultObj.getString("openid"));
                appletUserBO.setSession_key(resultObj.getString("session_key"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("授权异常！");
        }
        boolean isDefault = true;
        if (ObjectUtils.allNotNull(appletUserBO)) {
            MemberDO member = memberMapper.getMemberByOpenid(appletUserBO.getOpenid());
            if (StringUtils.isNotEmpty(appletAuthBO.getEncryptedData())
                    && StringUtils.isNotEmpty(appletAuthBO.getIv())) {
                isDefault = false;
                decryptUserInfo(appletAuthBO, appletUserBO.getSession_key());
            }
            if (member == null) {
                //TODO：新用户
                member = new MemberDO();
                member.setShopId(appletAuthBO.getShopId());
                member.setOpenid(appletUserBO.getOpenid());
                //TODO：生成6位随机盐
                SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
                member.setSalt(secureRandom.nextBytes(3).toHex());
                //TODO：找出当天排序
                int count = memberMapper.getTodayCount() + 1;
                member.setMemberSn(DateUtils.parseDateToStr("yyyyMMdd", new Date()) + String.format("%04d", count));
                member.setLoginTime(new Date());
                member.setCreateTime(new Date());
                member.setAvatar(host + "/logo/avatar.png");
                member.setNickname("会员" + member.getSalt());
                if (!isDefault) {
                    if (StringUtils.isNotEmpty(appletAuthBO.getAvatar())) {
                        member.setAvatar(appletAuthBO.getAvatar());
                    }
                    if (StringUtils.isNotEmpty(appletAuthBO.getNickname())) {
                        member.setNickname(appletAuthBO.getNickname());
                    }
                }
                memberMapper.insertSelective(member);
            } else {
                //TODO：旧用户
                member.setLoginTime(new Date());
                if (!isDefault) {
                    if (StringUtils.isNotEmpty(appletAuthBO.getAvatar())) {
                        member.setAvatar(appletAuthBO.getAvatar());
                    }
                    if (StringUtils.isNotEmpty(appletAuthBO.getNickname())) {
                        member.setNickname(appletAuthBO.getNickname());
                    }
                }
                memberMapper.updateByPrimaryKeySelective(member);
            }
            return member;
        } else {
            throw new BusinessException("服務器繁忙");
        }
    }

    @Override
    @Synchronized
    public MemberDO phoneAuth(AppletAuthBO appletAuthBO, Long memberId) {
        if ((memberId == null || memberId == 0 || appletAuthBO.getIsPhoneAuth() == null) && (appletAuthBO.getEncryptedData() == null || appletAuthBO.getIv() == null)) {
            throw new BusinessException("授权参数缺失！");
        }
        //TODO：查询店铺的appId和secret
        ShopAppletDO shopApplet = shopAppletService.getDetailByShopId(appletAuthBO.getShopId());
        if (shopApplet == null || shopApplet.getIsEnable() == null || shopApplet.getIsDelete() == 1) {
            throw new BusinessException("请联系运营平台重新开通小程序！");
        }
        if (shopApplet.getIsEnable() == 0) {
            throw new BusinessException("请联系运营平台重新上架小程序！");
        }
        String resultStr;
        JSONObject resultObj;
        String accessInfoStr = restTemplate.getForObject(
                accessTokenUrl, String.class,
                shopApplet.getAppletAppId(),
                shopApplet.getAppletSecret(),
                "client_credential");
        if (StringUtils.isEmpty(accessInfoStr)) {
            throw new BusinessException("网络异常");
        }
        try {
            resultObj = JSONObject.parseObject(accessInfoStr);
            if (resultObj.containsKey("errcode") && resultObj.getIntValue("errcode") != 0) {
                System.out.println(resultObj);
                throw new BusinessException("授权信息错误");
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put("code", appletAuthBO.getCode());
                resultStr = restTemplate.postForObject(phoneAuthUrl + resultObj.getString("access_token"), map, String.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("授权异常！");
        }
        if (StringUtils.isEmpty(resultStr)) {
            throw new BusinessException("网络异常");
        }
        AppletUserBO appletUserBO = new AppletUserBO();
        try {
            resultObj = JSONObject.parseObject(resultStr);
            if (resultObj.containsKey("errcode") && resultObj.getIntValue("errcode") != 0) {
                System.out.println(resultObj);
                throw new BusinessException("授权信息错误");
            } else {
                if (resultObj.containsKey("phone_info")) {
                    MemberDO member = memberMapper.selectByPrimaryKey(memberId);
                    member.setPhone(resultObj.getObject("phone_info", JSONObject.class).getString("purePhoneNumber"));
                    member.setLoginTime(new Date());
                    memberMapper.updateByPrimaryKeySelective(member);
                    //检查是否注册赠送了优惠券
                    AsyncManager.me().execute(ApiAsyncFactory.registerSendCoupon(member.getId(), member.getShopId()));
                    return member;
                } else {
                    appletUserBO.setOpenid(resultObj.getString("openid"));
                    appletUserBO.setSession_key(resultObj.getString("session_key"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("授权异常！");
        }
        if (ObjectUtils.allNotNull(appletUserBO)) {
            //授权成功
            //TODO：查询一下有没有该用户
            decryptUserInfo(appletAuthBO, appletUserBO.getSession_key());
            MemberDO member = memberMapper.getMemberByOpenid(appletUserBO.getOpenid());
            if (member == null) {
                //TODO：新用户
                member = new MemberDO();
                member.setShopId(appletAuthBO.getShopId());
                member.setOpenid(appletUserBO.getOpenid());
                //TODO：生成6位随机盐
                SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
                member.setSalt(secureRandom.nextBytes(3).toHex());
                //TODO：找出当天排序
                int count = memberMapper.getTodayCount() + 1;
                member.setMemberSn(DateUtils.parseDateToStr("yyyyMMdd", new Date()) + String.format("%04d", count));
                member.setLoginTime(new Date());
                member.setCreateTime(new Date());
                member.setAvatar(host + "/logo/avatar.png");
                member.setNickname("会员" + member.getSalt());
                if (StringUtils.isNotEmpty(appletAuthBO.getPhone())) {
                    member.setPhone(appletAuthBO.getPhone());
                }
                memberMapper.insertSelective(member);
            } else {
                //TODO：旧用户
                member.setLoginTime(new Date());
                if (StringUtils.isNotEmpty(appletAuthBO.getPhone())) {
                    member.setPhone(appletAuthBO.getPhone());
                }
                memberMapper.updateByPrimaryKeySelective(member);
            }
            //检查是否注册赠送了优惠券
            AsyncManager.me().execute(ApiAsyncFactory.registerSendCoupon(member.getId(), member.getShopId()));
            return member;
        } else {
            throw new BusinessException("服務器繁忙");
        }
    }

    private AppletAuthBO decryptUserInfo(AppletAuthBO appletAuthBO, String sessionKey) {
        // 被加密的数据
        byte[] dataByte = Base64.decode(appletAuthBO.getEncryptedData());
        // 加密秘钥
        byte[] keyByte = Base64.decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decode(appletAuthBO.getIv());
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(result);
                appletAuthBO.setAvatar(jsonObject.getString("avatarUrl"));
                appletAuthBO.setNickname(jsonObject.getString("nickName"));
                appletAuthBO.setPhone(jsonObject.getString("purePhoneNumber"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("获取信息失败！");
        }
        return appletAuthBO;
    }

}
